package cuid.sc20.laboratory.utils;


import cn.hutool.jwt.JWTHeader;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.security.Keys;
import org.springframework.stereotype.Component;

import javax.crypto.SecretKey;
import java.util.Base64;
import java.util.Date;
import java.util.Map;

@Component
public class JwtUtils {
    //定义默认有效期为3分钟 单位：毫秒
    public static final Long JWT_DEFAULT_EXPIRES = 3 * 60 * 1000L;
    //    GL/JpdE6hvpHD5xwDkM63s9H1e/39yPKAPqYRKSq9z0tsC1hRwsXUPnEC4cA7lsyzM0gisMUtRG7g8jXikKL1w==
    // 设置HS512密钥 secret
    //    public static final String JWT_KEY = "53ac32a18bab4aafb2ed835552fa797d8d6cd8f100db494397c7faa6e2628a914c2b5eade5ee429ca68e61a3c82dda1b";
    public static final String JWT_KEY = "GL/JpdE6hvpHD5xwDkM63s9H1e/39yPKAPqYRKSq9z0tsC1hRwsXUPnEC4cA7lsyzM0gisMUtRG7g8jXikKL1w==";
    //签发者
    public static final String ISSUER = "sc20";
    // 签名算法
    public static final SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS512;

    /**
     * 创建一个token
     */
    public static String createHmacJWT(Map<String, Object> claimsMap, Long expireTime) {
        //创建我们将要使用的JWT签名算法对（token）令牌进行签名
        //获取当前时间对应的Date对象，作为签发时间使用
        Date now = new Date();
        // expireTime 设置是Long 是引用类型， 引用类型的默认值是null  设置判断用户是否需要设置token有效时间
        if (expireTime == null) {
            //如果为空，将默认有效期赋值给expireTime
            expireTime = now.getTime() + JWT_DEFAULT_EXPIRES;
        }else{
            //结束时间 = 当前时间 + 设定的有效期时间
            expireTime = now.getTime() + expireTime;
        }
        //转换为date数据类型
        Date expireDate = new Date(expireTime);
        claimsMap.put("publishTime",now); //-- 签发时间
        claimsMap.put("ttl",expireDate);  //-- 过期时间
        JwtBuilder builder = Jwts.builder()
                .setHeaderParam(JWTHeader.TYPE, "JWT")    //一下两行就是Header
                .setHeaderParam(JWTHeader.ALGORITHM, signatureAlgorithm.getValue())
                .setClaims(claimsMap)
                .setIssuer(ISSUER)   //签发者
                // .setIssuedAt(now)   //签发时间
                .signWith(generalKey(), signatureAlgorithm); //使用ES256对称加密算法签名
        //.setExpiration(expireDate);   //设置过期时间
        //compact:规则构建JWT并将其序列化为紧凑的URL安全字符串
        return builder.compact();
    }
    /**
     * 加密明文密钥
     *
     */
    public static SecretKey generalKey() {
        //调用base64中的getDecoder方法获取解码器，调用解码器中的decode方法将明文密钥进行编码
        byte[] decodeKey = Base64.getDecoder().decode(JWT_KEY);
        //返回加密后的密钥
        return Keys.hmacShaKeyFor(decodeKey);
    }
    /**
     * 不带有过期时间的解析
     * 解析jwt 此处当解析不出的时候会抛出异常
     *   如果token是过期的，只要解析一定会抛出异常！
     */
    public static Claims parseHmacJWTWithOutExpTime(String token) {
        return Jwts.parserBuilder()//获取jwts的解析器
                .setSigningKey(generalKey())    //设置加密后的密钥进行比对
                .build()
                .parseClaimsJws(token)// (token)  解析传入的token字符串 当token过期了 parse方法会抛出过期时间异常
                .getBody();     // 拿到claims对象返回
    }
    //-- 带有过期时间的解析
    public static Claims parseHmacJWT(String token) {
        Claims body = Jwts.parserBuilder()//获取jwts的解析器
                .setSigningKey(generalKey())    //设置加密后的密钥进行比对
                .build()
                .parseClaimsJws(token)// (token)  解析传入的token字符串 当token过期了 parse方法会抛出过期时间异常
                .getBody();// 拿到claims对象返回
        Object o = body.get("ttl");
        Date expireDate = new Date(Long.parseLong(o+""));
        //- true  expireDate 在 当前之间之前
        if(expireDate.before(new Date())){
            return null;
        }
        return body;
    }
}



